package org.linlinjava.litemall.admin.task;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.linlinjava.litemall.admin.job.ShopMerchandiseJob;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallScheduledJob;
import org.linlinjava.litemall.db.domain.LitemallScheduledJobLog;
import org.linlinjava.litemall.db.domain.LitemallShopMerchandiseJob;
import org.linlinjava.litemall.db.service.LitemallScheduledJobLogService;
import org.linlinjava.litemall.db.service.LitemallScheduledJobService;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.TriggerBuilder.newTrigger;

@Slf4j
@Component
@RequiredArgsConstructor
public class ScheduledCronTaskRegistrar {

    private final Scheduler scheduler;

    private final LitemallScheduledJobService scheduledJobService;
    private final LitemallScheduledJobLogService scheduledJobLogService;

    /**
     * 添加定时任务
     *
     * @param quartzJob
     */
    public ResponseUtil.Response schedulerAdd(LitemallScheduledJob quartzJob,Class c) {
        String cronExpression = StringUtils.trim(quartzJob.getCron());
        String jobKey = getJobKey(quartzJob);
        try {
            // 启动调度器
            scheduler.start();
            // 构建job信息
            JobDetail jobDetail = JobBuilder.newJob(c).withIdentity(jobKey,"scTask").usingJobData("parameter", quartzJob.getName()).build();
            // 表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = cronSchedule(cronExpression);
            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = newTrigger().withIdentity(jobKey).withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            return ResponseUtil.fail(80900,"创建定时任务失败，请更正执行时间为未来的时间");
        } catch (Exception e) {
            return ResponseUtil.fail(80901,"任务创建失败！");
        }
        return ResponseUtil.ok("任务创建成功");
    }

    /**
     * 删除定时任务
     *
     * @param jobKey
     */
    public void schedulerDelete(String jobKey) {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobKey,"scTask"));
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobKey,"scTask"));
            scheduler.deleteJob(JobKey.jobKey(jobKey,"scTask"));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("删除定时任务失败");
        }
    }

    public ResponseUtil.Response schedulerPauseJob(String jobKey){
        try {
            scheduler.pauseJob(JobKey.jobKey(jobKey,"scTask"));
            return ResponseUtil.ok();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseUtil.fail("暂停指定的任务失败");
        }
    }
    public ResponseUtil.Response schedulerResumeJob(String jobKey){
        try {
            scheduler.resumeJob(JobKey.jobKey(jobKey,"scTask"));
            return ResponseUtil.ok();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseUtil.fail("恢复指定的任务失败");
        }
    }

    public ResponseUtil.Response schedulerTriggerJob(String jobKey){
        try {
            scheduler.triggerJob(JobKey.jobKey(jobKey,"scTask"));
            return ResponseUtil.ok();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
           return ResponseUtil.fail("立即执行一次任务失败");
        }
    }

    public void schedulerRescheduleJob(LitemallScheduledJob quartzJob){
        try {
            String cronExpression = StringUtils.trim(quartzJob.getCron());
            // 定义触发器的TriggerKey
            TriggerKey triggerKey = new TriggerKey(getJobKey(quartzJob), "scTask"); // 替换为实际的触发器名称和分组

            // 获取现有的触发器
            Trigger oldTrigger = scheduler.getTrigger(triggerKey);

            if (oldTrigger != null) {
                // 修改现有的触发器的调度时间（例如修改cron表达式）
                CronScheduleBuilder scheduleBuilder = cronSchedule(cronExpression);
                Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity(getJobKey(quartzJob), "scTask")
                        .withSchedule(scheduleBuilder)
                        .startNow()
                        .build();
                // 更新触发器
                scheduler.rescheduleJob(triggerKey, trigger);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("更新任务失败");
        }
    }
    public Boolean checkExists(LitemallScheduledJob quartzJob){
        try {
            return scheduler.checkExists(JobKey.jobKey(getJobKey(quartzJob),"scTask"));
        } catch (SchedulerException e) {
            return false;
        }
    }

    private static String getJobKey(LitemallScheduledJob quartzJob) {
        String jobKey = quartzJob.getId().toString();
        return jobKey;
    }

    public void scheduleJobLog(JobExecutionContext jobExecutionContext){
        // 获取当前作业的 JobDetail
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        // 获取作业的 JobKey
        JobKey jobKey = jobDetail.getKey();
        // 获取 JobKey 的名称
        String jobName = jobKey.getName();
        LitemallScheduledJob scheduledJob = scheduledJobService.getById(jobName);

        LitemallScheduledJobLog jobLog = LitemallScheduledJobLog.builder()
                .className(jobDetail.getJobClass().getName())
                .cron(scheduledJob.getCron())
                .addTime(LocalDateTime.now())
                .group("scTask")
                .desc(scheduledJob.getDesc())
                .taskName(scheduledJob.getName())
                .nextFireTime(jobExecutionContext.getNextFireTime())
                .jobName(jobName)
                .jobGroup(jobKey.getGroup())
                .fireInstanceId(jobExecutionContext.getNextFireTime())
                .parameter(scheduledJob.getName())
                .build();
        scheduledJobLogService.save(jobLog);
    }

}
 
 
